package com.suse.warmstill.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.suse.warmstill.common.enums.ResponseEnum;
import com.suse.warmstill.common.exception.BusinessException;
import com.suse.warmstill.common.model.ListPageModel;
import com.suse.warmstill.entity.TbRole;
import com.suse.warmstill.entity.TbUser;
import com.suse.warmstill.mapper.TbRoleMapper;

import com.suse.warmstill.mapper.TbUserMapper;
import com.suse.warmstill.service.*;
import com.suse.warmstill.transaction.TransactionService;
import com.suse.warmstill.vo.ConditionVO;
import com.suse.warmstill.vo.RoleVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * @author 黄靖
 * @author 2022-10-20 00:50
 * description:
 **/
@Service
@Slf4j
public class RoleServiceImpl implements RoleService, BaseService<RoleVo, TbRole> {

    @Autowired
    private TbRoleMapper roleMapper;

    @Autowired
    private RoleMenuService roleMenuService;

    @Autowired
    private RoleResourceService roleResourceService;

    @Autowired
    private UserROleService userROleService;

    @Autowired
    private TransactionService transactionService;

    @Autowired
    private TbUserMapper userMapper;


    @Override
    public ListPageModel<RoleVo> listRoles(ConditionVO conditionVO) {
        final Page<TbRole> page = new Page<>(conditionVO.getCurrent(), conditionVO.getSize());


        final LambdaQueryWrapper<TbRole> wrapper = new LambdaQueryWrapper<>();

        if (StringUtils.isNotBlank(conditionVO.getKeyword())) {
            wrapper.like(TbRole::getRoleName, conditionVO.getKeyword());
        }

        final Page<TbRole> pagelist = roleMapper.selectPage(page, wrapper);


        /*
         * 完成 RoleVo 的组装
         * */
        final ListPageModel<RoleVo> roleVoListPageModel = new ListPageModel<RoleVo>();
        roleVoListPageModel.setCurrentPage((int) pagelist.getCurrent());
        roleVoListPageModel.setPageCount((int) pagelist.getPages());
        roleVoListPageModel.setPageSize((int) pagelist.getSize());
        roleVoListPageModel.setDataSize((int) pagelist.getTotal());

        final List<TbRole> records = pagelist.getRecords();

        final List<RoleVo> roleVos = new ArrayList<>();
        records.stream().forEach((role) -> {
            RoleVo roleVo = toVo(role);

            final Long id = roleVo.getId();
            final List<Long> menus = roleMenuService.listMenuByRoleId(id);
            roleVo.setMenuList(menus);

            final List<Long> resources = roleResourceService.listResourceByRoleId(id);
            roleVo.setResourceList(resources);
            roleVos.add(roleVo);

        });


        roleVoListPageModel.setList(roleVos);

        return roleVoListPageModel;
    }


    @Override
    public void disableRoles(List<Long> roleIds) {


        roleIds.stream().forEach((roleId) -> {
            roleMapper.deleteById(roleId);
            roleMenuService.deleteByRoleId(roleId);
            roleResourceService.deleteByRoleId(roleId);
            userROleService.deleteByRoleId(roleId);
        });

    }


    @Override
    public void updateRoleMenu(RoleVo roleVo) {
        /*
         * 修改 role表的字段
         * */
        final TbRole tbRole = new TbRole();
        tbRole.setId(roleVo.getId());
        tbRole.setRoleName(roleVo.getRoleName());
        tbRole.setRoleLabel(roleVo.getRoleLabel());
        roleMapper.updateById(tbRole);

        /*
         * 修改 菜单权限
         * */

        if (roleVo.getMenuList().size() != 0) {
            /*
             * 批量删除 原有的 role-menu
             * */
            roleResourceService.deleteByRoleId(roleVo.getId());
            /*
             * 批量插入 新的 role-menu
             * */

            roleMenuService.inserRoleMenu(roleVo.getId(), roleVo.getMenuList());

        }

    }


    @Override
    public void insertRole(RoleVo roleVo) {
        /*
         * 先从数据库查，如果有 ，就抛异常失败
         * */

        final TbRole tbRole1 = roleMapper.selectOne(new LambdaQueryWrapper<TbRole>().eq(TbRole::getRoleName, roleVo.getRoleName()));
        if (ObjectUtils.isNotEmpty(tbRole1)) {
            throw new BusinessException(ResponseEnum.REPEAT_DATA.getCode(), "当前角色已经注册过，请勿重新注册");
        }

        /*
         * 插入role表
         * */
        final TbRole tbRole = new TbRole();

        tbRole.setRoleName(roleVo.getRoleName());
        tbRole.setRoleLabel(roleVo.getRoleLabel());
        tbRole.setIsDisable(0);
        tbRole.setGmtCreate(LocalDateTime.now());

        roleMapper.insert(tbRole);
        /*
         * 查询出 role，进行 其他资源你的关联
         * */


        final Long roleId = tbRole.getId();

        /*
         * 如果 传来的 前端资源列表不为空
         * */
        if (CollectionUtil.isNotEmpty(roleVo.getResourceList())) {
            roleResourceService.insertRoleResource(roleId, roleVo.getResourceList());
        }

        /*
         * 如果传来的  菜单资源不为空
         * */

        if (CollectionUtil.isNotEmpty(roleVo.getMenuList())) {
            roleMenuService.inserRoleMenu(roleId, roleVo.getMenuList());
        }

    }


    @Override
    public RoleVo toVo(TbRole entity) {
        final RoleVo roleVo = new RoleVo();
        roleVo.setRoleName(entity.getRoleName());
        roleVo.setRoleName(entity.getRoleName());
        roleVo.setId(entity.getId());

        roleVo.setIsDisable(entity.getIsDisable());
        roleVo.setCreateDate(entity.getGmtCreate());
        return roleVo;
    }

    /*
     * 禁用单个角色
     * */

    @Override
    public void disableRole(Long roleId) {
        /*
         * 禁用之前 先查询，角色 有没有对应的user  如果有，就不能删除,同时返回用户的名字
         * */

        final List<Long> userIdByRoleIds = userROleService.getUserIdByRoleId(roleId);


        if (CollectionUtil.isNotEmpty(userIdByRoleIds)) {
            final ArrayList<String> names = new ArrayList<>();
            userIdByRoleIds.stream().forEach((id) -> {
                final TbUser user = userMapper.selectById(id);
                names.add(user.getUsername());
            });

            throw new BusinessException(ResponseEnum.HAS_USER.getCode(), ResponseEnum.HAS_USER.getMsg() + "用户是：" + names);
        }


        transactionService.process(() -> {
            roleMapper.deleteById(roleId);
            roleMenuService.deleteByRoleId(roleId);
            roleResourceService.deleteByRoleId(roleId);
            userROleService.deleteByRoleId(roleId);
        });

    }

    @Override
    public void updateRoleResource(RoleVo roleVo) {
        /*
         * 插入role表
         * */
        final TbRole tbRole = new TbRole();
        tbRole.setId(roleVo.getId());
        tbRole.setRoleName(roleVo.getRoleName());
        tbRole.setRoleLabel(roleVo.getRoleLabel());
        tbRole.setIsDisable(0);
        roleMapper.insert(tbRole);
        /*
         * 查询出 role，进行 其他资源你的关联
         * */
        final LambdaQueryWrapper<TbRole> wrapper = new LambdaQueryWrapper<>();

        wrapper.eq(TbRole::getRoleName, tbRole.getRoleName());

        final Long roleId = roleMapper.selectOne(wrapper).getId();

        if (ObjectUtils.isNotEmpty(roleVo.getResourceList())) {
            /*
             * 批量删除 role - resource
             * */
            roleResourceService.deleteByRoleId(roleId);
            /*
             * 批量添加 role -resource
             * */
            roleResourceService.insertRoleResource(roleId, roleVo.getResourceList());
        }


    }
}
